package org.harsh.dispatch;


import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDeptService;
import io.jpower.kcp.netty.ChannelOptionHelper;
import io.jpower.kcp.netty.UkcpChannel;
import io.jpower.kcp.netty.UkcpChannelOption;
import io.jpower.kcp.netty.UkcpClientChannel;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.handler.traffic.ChannelTrafficShapingHandler;
import lombok.extern.slf4j.Slf4j;
import org.harsh.transmission.client.ClientChannelInitializer;
import org.harsh.transmission.common.*;
import org.harsh.transmission.common.codec.FileMsgCodec;
import org.harsh.transmission.common.codec.MsgPackDecoder;
import org.harsh.transmission.common.codec.MsgPackEncoder;
import org.harsh.transmission.common.codec.PlainMsgCodec;
import org.harsh.transmission.domain.TransTask;
import org.harsh.transmission.service.ITransTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Set;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * 调度层，生成任务队列，并选择对应的Channel进行传输
 */
@Slf4j
@Component("dispatcher")
public class Dispatcher {
    //    private synchronized LinkedTransferQueue

//    public static EventLoopGroup group = new NioEventLoopGroup();

    @Autowired
    private ISysDeptService sysDeptService;
    @Autowired
    private ITransTaskService transTaskService;


    public void init() {
        List<SysDept> deptList = sysDeptService.selectOtherDeptList();
        for (SysDept sysDept : deptList) {
        //    connect(sysDept);
        }
    }

    /**
     * 装载任务队列
     */
    public void loadQueue() {
        // 装载已建立连接的节点任务
//        Set<Long> connectedNodes = CommVars.getNode();
        List<Long> connectedNodes = NodeStatusCheckTask.getConnectivity();
        for(long nodeId : connectedNodes ) {
            PriorityBlockingQueue<TransTask> taskQueue;
            if(CommVars.nodeTaskQueue.containsKey(nodeId)) {
                taskQueue = CommVars.nodeTaskQueue.get(nodeId);
            } else {
                taskQueue = new PriorityBlockingQueue<TransTask>();
            }

            if(taskQueue.size() < 10) {
                int len = 10 - taskQueue.size();
                List<TransTask> taskList = transTaskService.selectUnTransTask(nodeId, len);
                for(TransTask task : taskList) {
                    if(!CommVars.loadedTask.containsKey(task.getTaskId())) {
                        taskQueue.put(task);
                        CommVars.insertLoadedTask(task);
                    }
                }
            }
            CommVars.nodeTaskQueue.put(nodeId, taskQueue);
        }

        // 单向任务
        List<TransTask> unitaskList = transTaskService.selectUnuniTransTask(10);
        for(TransTask task : unitaskList) {
            if(!CommVars.loadedTask.containsKey(task.getTaskId())) {
                PriorityBlockingQueue<TransTask> taskQueue;
                if(CommVars.nodeTaskQueue.containsKey(task.getRecvNode())) {
                    taskQueue = CommVars.nodeTaskQueue.get(task.getRecvNode());
                } else {
                    taskQueue = new PriorityBlockingQueue<TransTask>();
                }
                taskQueue.put(task);
                CommVars.insertLoadedTask(task);
                CommVars.nodeTaskQueue.put(task.getRecvNode(), taskQueue);
            }
        }

        // 组播或广播任务
        long otherTypeTaskNode = -1l;
        PriorityBlockingQueue<TransTask> otherTaskQueue;
        if(CommVars.nodeTaskQueue.containsKey(otherTypeTaskNode)) {
            otherTaskQueue = CommVars.nodeTaskQueue.get(otherTypeTaskNode);
        } else {
            otherTaskQueue = new PriorityBlockingQueue<TransTask>();
        }
        if(otherTaskQueue.size() < 10) {
            int len = 10 - otherTaskQueue.size();
            List<TransTask> taskList = transTaskService.selectUnTransOtherTypeTask(len);
            for(TransTask task : taskList) {
                if(!CommVars.loadedTask.containsKey(task.getTaskId())) {
                    otherTaskQueue.put(task);
                    CommVars.insertLoadedTask(task);
                }
            }
        }
        CommVars.nodeTaskQueue.put(otherTypeTaskNode, otherTaskQueue);
    }
}
